package com.epin.config.mybatis;

import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.annotation.After;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
import org.aspectj.lang.annotation.Pointcut;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.core.annotation.Order;
import org.springframework.stereotype.Component;

import com.epin.base.annotation.TargetDataSource;

/**
 * 切换数据源Advice
 *
 * @author 单红宇(365384722)
 * @myblog http://blog.csdn.net/catoop/
 * @create 2016年1月23日
 */
@Aspect
@Order(-1)// 保证该AOP在@Transactional之前执行
@Component
public class DynamicDataSourceAspect {

    private static final Logger logger = LoggerFactory.getLogger(DynamicDataSourceAspect.class);

    @Pointcut("execution (* com.baomidou.mybatisplus.service..*.*(..))")
    public  void controllerAspect() {
    }

    @Before("controllerAspect()")
    public void doBefore(JoinPoint joinPoint) throws Throwable {
        //logger.info("==========执行controller前置通知============");
        if(logger.isInfoEnabled()){
            logger.info("before " + joinPoint);
        }
        TargetDataSource ds = joinPoint.getTarget().getClass().getAnnotation(TargetDataSource.class);
        if (ds != null){
            this.changeDataSource(joinPoint,ds);
        }
    }

    @After("controllerAspect()")
    public void doAfter(JoinPoint joinPoint) {
        //logger.info("==========执行controller后通知===============");
        if(logger.isInfoEnabled()){
            logger.info("after " + joinPoint);
        }
        TargetDataSource ds = joinPoint.getTarget().getClass().getAnnotation(TargetDataSource.class);
        if (ds != null){
            this.restoreDataSource(joinPoint,ds);
        }
    }


    @Before("@annotation(ds)")
    public void changeDataSource(JoinPoint point, TargetDataSource ds) throws Throwable {
        String dsId = ds.name();
        if (!DynamicDataSourceContextHolder.containsDataSource(dsId)) {
            logger.error("数据源[{}]不存在，使用默认数据源 > {}", ds.name(), point.getSignature());
        } else {
            logger.debug("Use DataSource : {} > {}", ds.name(), point.getSignature());
            DynamicDataSourceContextHolder.setDataSourceType(ds.name());
        }
    }

    @After("@annotation(ds)")
    public void restoreDataSource(JoinPoint point, TargetDataSource ds) {
        logger.debug("Revert DataSource : {} > {}", ds.name(), point.getSignature());
        DynamicDataSourceContextHolder.clearDataSourceType();
    }

}